package jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 预编译SQL语句
 * 在LoginDemo案例中，由于拼接SQL可能存在改变语义的情况(SQL注入攻击)，因此解决办法为使用预编译SQL
 *
 * 预编译SQL可以将用户输入的值先使用"?"进行占位来定义SQL语义。然后先将该SQL发送给数据库使其理解语义，然后
 * 再将用户输入的数据发送过去来表示"?"部分的值，此时数据库仅会将发送过去的数据当值"值"看待，不会改变SQL语义
 *
 */
public class JDBCDemo7 {
    public static void main(String[] args) {
        User user = InputUtil.getInputObject(new User(),"欢迎登录","登录");
        System.out.println(user);
        try (Connection connection = DBUtil.getConnection()) {
            /*
                使用预编译SQL规定语义
                SELECT id,username,password,nickname,age
                FROM userinfo
                WHERE username=? AND password=?
                上述SQL语义已经明确，唯一缺失的就是过滤条件中用户名的值和密码的值
                先将该SQL发送给数据库，数据库就可以明确语义并生成执行计划，但是还不能真正执行该SQL，因为
                还缺少值，之后我们会再陆续将值发送给数据库，此时数据库仅会将接收到的内容当作"值"看待，无论
                该值中是否包含SQL关键字，都是当作值看待，不会再改变SQL语义
             */

            String sql = "SELECT id,username,password,nickname,age " +
                         "FROM userinfo " +
                         "WHERE username=? AND password=?";
            //在创建执行对象时先将预编译SQL发送给数据库(数据库就明确了语义，生成执行计划)
            PreparedStatement ps = connection.prepareStatement(sql);
//            ps.setString(1,"范传奇");//指定第一个?的值是"范传奇"
//            ps.setString(2,"123456");
            ps.setString(1,user.getUsername());
            ps.setString(2,user.getPassword());
            ResultSet rs = ps.executeQuery();//执行是不必再传入SQL了
            if(rs.next()){
                System.out.println("登录成功");
            }else{
                System.out.println("登录失败");
            }


        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}


